package com.geor.gcv.core.util;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.UnsupportedEncodingException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.TreeSet;
import java.util.UUID;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.swing.filechooser.FileSystemView;

import org.opencv.core.Mat;

import com.geor.common.file.FileDigestor;
import com.geor.gcv.core.mat.Mats;

/**
 * 对数据操作
 * 
 * @author geor.lusongnan
 *
 */
public class DataTool {
	public static final String DESKTOP = FileSystemView.getFileSystemView().getHomeDirectory().getAbsolutePath();
	public static final String HOME = System.getProperty("user.dir");

	/**
	 * 返回时间名称
	 * 
	 * @return
	 */
	public static String getTimestampName() {
		SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddhhmmss");
		return sdf.format(new Date());
	}

	/**
	 * 随机生成数字start-end
	 * 
	 * @param start
	 * @param end
	 * @return
	 */
	public static float random(int start, int end) {
		Random rm = new Random();
		return (float) (rm.nextFloat() * (end - start)) + (float) (start);
	}

	public static String getUUID() {
		return UUID.randomUUID().toString().replace("-", "");
	}

	/**
	 * 将字符串转16进制字符串
	 * 
	 * @param str
	 * @return
	 */
	public static String strToHexStr(String str) {
		char[] chars = "0123456789ABCDEF".toCharArray();
		StringBuilder sb = new StringBuilder("");
		byte[] bs = str.getBytes();
		int bit;
		for (int i = 0; i < bs.length; i++) {
			bit = (bs[i] & 0x0f0) >> 4;
			sb.append(chars[bit]);
			bit = bs[i] & 0x0f;
			sb.append(chars[bit]);
		}
		return sb.toString();
	}

	/**
	 * 将字符串转为10进制字符串
	 * 
	 * @param str
	 * @return
	 */
	public static String strToDecimalStr(String str) {
		return String.valueOf(Integer.parseInt(strToHexStr(str), 16));
	}

	/**
	 * 将字符转为数字
	 * 
	 * @param str
	 * @return
	 */
	public static int strTOnumber(String str) {
		return Integer.parseInt(strToHexStr(str), 16);
	}

	/**
	 * 将数字转为字符
	 * 
	 * @param number
	 * @return
	 */
	public static String numberTOstr(int number) {
		return convertUTF8ToString(String.valueOf(Integer.toHexString(number)));
	}

	/**
	 * 将16进制字符串转位字符串
	 * 
	 * @param number
	 * @return
	 */
	public static String convertUTF8ToString(String number) {
		if (number == null || number.equals("")) {
			return null;
		}

		try {
			number = number.toUpperCase();
			int total = number.length() / 2;
			int pos = 0;
			byte[] buffer = new byte[total];
			for (int i = 0; i < total; i++) {
				int start = i * 2;
				buffer[i] = (byte) Integer.parseInt(number.substring(start, start + 2), 16);
				pos++;
			}
			return new String(buffer, 0, pos, "UTF-8");
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
		return number;
	}

	/**
	 * 取集合 间距最大的位置
	 * 
	 * @param rows
	 * @return
	 */
	public static int getListPoorMaxValue(List<Integer> rows) {
		int row = 0;
		if (rows.size() == 2) {
			return row;
		}
		if (rows.size() > 2) {
			// 切割 行距 从而判断 在那一行切割
			List<Integer> lists = new ArrayList<Integer>();
			for (int i = 1; i < rows.size(); i++) {
				lists.add(rows.get(i) - rows.get(i - 1));
			}
			for (int i = 1; i < lists.size(); i++) {
				int poor = lists.get(row);
				if (poor < lists.get(i)) {
					row = i;
				}
			}
		}
		return row;
	}

	/**
	 * 求整型集合元素和
	 * 
	 * @param success
	 * @return
	 */
	public static Integer listAverage(List<Integer> list) {
		int sum = 0;

		for (Integer integer : list) {
			sum += integer;
		}

		return sum / list.size();
	}

	/**
	 * 获取集合最小值的下标
	 * 
	 * @param temps
	 * @return
	 */
	public static int getListMinIndex(List<Integer> temps) {
		int index = 0;
		for (int i = 1; i < temps.size(); i++) {
			int temp = temps.get(index);
			if (temp > temps.get(i)) {
				index = i;
			}
		}
		return index;
	}

	/**
	 * 获取集合最大值下标
	 * 
	 * @param temps
	 * @return
	 */
	public static int getListMaxIndex(List<Integer> temps) {
		int index = 0;
		for (int i = 1; i < temps.size(); i++) {
			int temp = temps.get(index);
			if (temp < temps.get(i)) {
				index = i;
			}
		}
		return index;
	}

	/**
	 * 获取map最小值key的集合
	 * 
	 * @param maps
	 * @return
	 */
	public static List<Integer> getMapMinIndexList(Map<Integer, Integer> maps) {
		List<Integer> lists = new ArrayList<Integer>();
		List<Integer> temps = new ArrayList<Integer>();
		for (int key : maps.keySet()) {
			temps.add(maps.get(key));
		}

		int value = temps.get(getListMinIndex(temps));
		for (int key : maps.keySet()) {
			int i = maps.get(key);
			if (i == value) {
				lists.add(key);
			}
		}
		temps.clear();
		return lists;
	}

	/**
	 * 清除重复元素
	 * 
	 * @param lists
	 * @return
	 */
	public static List<String> clearRepat(List<String> lists) {
		if (null != lists && lists.isEmpty()) {
			return lists;
		}

		List<String> temps = new ArrayList<String>();
		for (String str : lists) {
			if (!temps.contains(str)) {
				temps.add(str);
			}
		}
		return temps;
	}

	/**
	 * 过滤重复字符串
	 * 
	 * @param str
	 * @return
	 */
	public static String clearRepat(String str) {
		TreeSet<String> noReapted = new TreeSet<String>();

		for (int i = 0; i < str.length(); i++) {
			noReapted.add("" + str.charAt(i));
		}

		str = "";

		for (String index : noReapted) {
			str += index;
		}
		return str;
	}

	/**
	 * 检查金额格式
	 * 
	 * @param number
	 * @return
	 */
	public static boolean checkMoneyFormat(String number) {
		if (number.contains(".") || number.contains(",")) {

			int curIndex = 0;
			int oldIndex = 0;
			// 假如识别结果为:2,153,360.22
			for (int n = 0; n < number.length(); n++) {
				char ch = number.charAt(n);
				// 判断这些字符 记录位置
				if (ch == '.' || ch == ',') {
					// 将该位置记录
					curIndex = n;
					if (oldIndex != 0) {
						// 判断是否间距3个数字，则该格式正确
						int poor = curIndex - oldIndex;
						if (poor != 4 || n == 0) {
							return false;
						}
					}
				}
				if ((n == 0) && (ch == ',' || ch == '.')) {
					return false;
				}

				oldIndex = curIndex;
			}
			return true;
		} else {
			return false;
		}
	}

	public static String getFileSHA1(File file) {
		return FileDigestor.getDigest(file, "SHA-1");
	}

	/**
	 * 将InputStream转换成byte数组
	 * 
	 * @param in
	 *            InputStream
	 * @return byte[]
	 * @throws IOException
	 */
	public static byte[] InputStreamTOByte(InputStream in) {

		ByteArrayOutputStream outStream = new ByteArrayOutputStream();
		byte[] data = new byte[400];
		int count = -1;
		try {
			while ((count = in.read(data, 0, 400)) != -1)
				outStream.write(data, 0, count);
		} catch (IOException e) {
			e.printStackTrace();
		}

		data = null;
		return outStream.toByteArray();
	}

	public static InputStream ByteTOInputStream(byte[] buf) {
		return new ByteArrayInputStream(buf);
	}

	public static Mat InputStreamToMat(InputStream is) {
		byte[] bytes = DataTool.InputStreamTOByte(is);
		Mat img = Mats.ByteToMat(bytes);
		return img;
	}

	public static void ObjectToFile(Object obj, File file) throws FileNotFoundException, IOException {
		ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(file));
		oos.writeObject(obj);
		oos.flush();
		oos.close();
	}

	/**
	 * 得到间距最大的2个元素集合
	 * 
	 * @param lists
	 * @return
	 */
	public static List<Integer> getMaxInterval(List<Integer> lists) {
		List<Integer> temps = new ArrayList<Integer>();
		if (lists.size() > 1) {
			for (int i = 1; i < lists.size(); i += 2) {
				int poor = lists.get(i) - lists.get(i - 1);
				temps.add(poor);
			}
		}

		int index = DataTool.getListMaxIndex(temps);
		List<Integer> as = new ArrayList<Integer>();
		as.add(lists.get(index * 2));
		as.add(lists.get(index * 2 + 1));

		return as;
	}

	public static byte[] ObjectToByte(Object obj) {
		byte[] bytes = null;
		ByteArrayOutputStream bo = null;
		ObjectOutputStream oo = null;
		try {
			bo = new ByteArrayOutputStream();
			oo = new ObjectOutputStream(bo);
			oo.writeObject(obj);
			bytes = bo.toByteArray();
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				bo.close();
				oo.close();
			} catch (Exception e) {
			}
		}
		return bytes;
	}

	public static Object ByteToObject(byte[] bytes) throws Exception {
		Object obj = null;
		ByteArrayInputStream bi = null;
		ObjectInputStream oi = null;
		try {
			bi = new ByteArrayInputStream(bytes);
			oi = new ObjectInputStream(bi);
			obj = oi.readObject();
		} finally {
			try {
				if (bi != null)
					bi.close();
				if (oi != null)
					oi.close();
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		return obj;
	}

	public static boolean isDate(String sDate) {
		String datePattern1 = "\\d{4}-\\d{2}-\\d{2}";
		String datePattern2 = "^((\\d{2}(([02468][048])|([13579][26]))"
				+ "[\\-\\/\\s]?((((0?[13578])|(1[02]))[\\-\\/\\s]?((0?[1-9])|([1-2][0-9])|"
				+ "(3[01])))|(((0?[469])|(11))[\\-\\/\\s]?((0?[1-9])|([1-2][0-9])|(30)))|(0?2[\\-\\/\\s]?"
				+ "((0?[1-9])|([1-2][0-9])))))|(\\d{2}(([02468][1235679])|([13579][01345789]))[\\-\\/\\s]?("
				+ "(((0?[13578])|(1[02]))[\\-\\/\\s]?((0?[1-9])|([1-2][0-9])|(3[01])))|(((0?[469])|(11))[\\-\\/\\s]?"
				+ "((0?[1-9])|([1-2][0-9])|(30)))|(0?2[\\-\\/\\s]?((0?[1-9])|(1[0-9])|(2[0-8]))))))";
		if ((sDate != null)) {
			Pattern pattern = Pattern.compile(datePattern1);
			Matcher match = pattern.matcher(sDate);
			if (match.matches()) {
				pattern = Pattern.compile(datePattern2);
				match = pattern.matcher(sDate);
				return match.matches();
			} else {
				return false;
			}
		}
		return false;
	}

}
